package org.dftproject.genesis.ui.pages;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

public class PageHistory {

	private final List<IPageHistoryListener> listeners = new LinkedList<IPageHistoryListener>();
	
	private final List<PageHistoryEntry> history = new ArrayList<PageHistoryEntry>();
	private int activeEntry = 0;
	
	public PageHistoryEntry getEntry(int index) {
		return history.get(index);
	}

	public PageHistoryEntry[] getForwardEntries(int limit) {
		int length = history.size() - activeEntry - 1;
		length = Math.max(0, Math.min(length, limit));
		PageHistoryEntry[] entries = new PageHistoryEntry[length];
		for (int i = 0; i < length; i++)
			entries[i] = getEntry(activeEntry + 1 + i);
		return entries;
	}

	public PageHistoryEntry[] getBackEntries(int limit) {
		int length = Math.min(activeEntry, limit);
		PageHistoryEntry[] entries = new PageHistoryEntry[length];
		for (int i = 0; i < length; i++)
			entries[i] = getEntry(activeEntry - 1 - i);
		return entries;
	}

	public boolean canForward() {
		return (0 <= activeEntry + 1) && (activeEntry + 1 < history.size());
	}

	public boolean canBack() {
		return (0 <= activeEntry - 1) && (activeEntry - 1 < history.size());
	}
	
	public void addEntry(PageHistoryEntry entry) {
		removeForwardEntries();
		history.add(entry);
		activeEntry = history.size() - 1;
		notifyListeners();
	}
	
	protected void removeForwardEntries() {
		int length = history.size();
		for (int i = activeEntry + 1; i < length; i++)
			history.remove(activeEntry + 1);
	}

	public void forward() {
		if (canForward())
			shiftEntry(true);
	}

	public void back() {
		if (canBack())
			shiftEntry(false);
	}

	protected void shiftEntry(boolean forward) {
		if (forward)
			++activeEntry;
		else
			--activeEntry;
		PageHistoryEntry entry = getEntry(activeEntry);
		if (entry != null) {
			gotoEntry(entry);
		}
	}
	
	public void shiftCurrentEntry(PageHistoryEntry entry) {
		activeEntry = history.indexOf(entry);
        gotoEntry(entry);
	}
	
	protected void gotoEntry(PageHistoryEntry entry) {
		IWorkbench workbench = PlatformUI.getWorkbench();
		IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
		IWorkbenchPage workbenchPage = window.getActivePage();
		entry.navigate(PageManager.getActiveTabPart(workbenchPage));
		notifyListeners();
	}
	
	public void addListener(IPageHistoryListener listener) {
		listeners.add(listener);
	}
	
	public void removeListener(IPageHistoryListener listener) {
		listeners.remove(listener);
	}
	
	protected void notifyListeners() {
		for (IPageHistoryListener listener : listeners)
			listener.pageChanged(this);
	}

	public PageHistoryEntry getActiveEntry() {
		return getEntry(activeEntry);
	}

}
